#include "StdAfx.h"
#include "cmemspace.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


BOOL CSmpMemSpace::Read(DWORD dwRdAddr, BYTE* pbBuf, DWORD dwSize)
{
	BYTE* p=m_Buf+dwRdAddr%sizeof(m_Buf);
	memcpy(pbBuf, p, min(dwSize, sizeof(m_Buf)-(dwRdAddr%sizeof(m_Buf))) );
	return TRUE;
}

BOOL CSmpMemSpace::Write(DWORD dwWtAddr, BYTE* pbBuf, DWORD dwSize)
{
	BYTE* p=m_Buf+dwWtAddr%sizeof(m_Buf);
	memcpy(p, pbBuf, min(dwSize, sizeof(m_Buf)-(dwWtAddr%sizeof(m_Buf))));
	return TRUE;
}



BOOL CeCpyFl2Dev(TCHAR* pszLocFile, WCHAR* pwszRmtFile, BOOL fOvWt)
{
	BOOL fRet=FALSE;
	HANDLE hRmtFl=INVALID_HANDLE_VALUE;
	//
	HANDLE hLocFl=CreateFile(pszLocFile, GENERIC_WRITE|GENERIC_READ,
		0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if(INVALID_HANDLE_VALUE!=hLocFl)
	{

		hRmtFl=CeCreateFile(	pwszRmtFile, GENERIC_WRITE|GENERIC_READ,
			0, NULL, fOvWt?CREATE_ALWAYS:CREATE_NEW, 
			FILE_ATTRIBUTE_NORMAL, NULL);
		if(INVALID_HANDLE_VALUE!=hRmtFl)
		{
			BYTE Buf[1024];
			DWORD dwRdLen, dwWtLen;
			while(1)
			{
				if(0!=ReadFile(hLocFl,Buf, sizeof(Buf), &dwRdLen, NULL))
				{
					if(0!=CeWriteFile(hRmtFl, Buf, dwRdLen, &dwWtLen, NULL))
					{
						if(dwRdLen!=sizeof(Buf))
						{
							fRet=TRUE;
							break;
						}
					}
				}
			}
		}
	}

	if(INVALID_HANDLE_VALUE!=hLocFl){CloseHandle(hLocFl);}
	if(INVALID_HANDLE_VALUE!=hRmtFl){CeCloseHandle(hRmtFl);}

	return fRet;
}

WCHAR CEMemSpace::m_wstrDll[]={L"RApiInvokSvr"};
WCHAR CEMemSpace::m_wstrFun[]={L"RAPIFun"};


BOOL CEMemSpace::Connect(void* pv)
{
	RAPIINIT rapiinit;
	rapiinit.cbSize=sizeof(rapiinit);
	rapiinit.heRapiInit=NULL;
	rapiinit.hrRapiInit=0;

	if(FAILED(CeRapiInitEx(&rapiinit)))
	{
		MessageBox(NULL,_T("Pls make Activesync connected!"), NULL, MB_OK);
		return FALSE;
	}

	DWORD dwTo=*(reinterpret_cast<DWORD*>(pv));
	DWORD dwWt=WaitForSingleObject(rapiinit.heRapiInit, dwTo);
	if(WAIT_OBJECT_0!=dwWt)
	{
		TRACE(_T("Can't get connect!"));
		CeRapiUninit();
		return FALSE;
	}

	DWORD	cbOut;
	if(FAILED(CeRapiInvoke(	m_wstrDll, m_wstrFun, NULL,
								NULL, &cbOut, NULL, &m_pStream, 0)))
	{
		DWORD dwErr=CeGetLastError();
		if(ERROR_FILE_NOT_FOUND==dwErr)
		{
			USES_CONVERSION;
			// copy dll to device
			CStringW cstrwFile=L"\\Windows\\";
			cstrwFile+=m_wstrDll;
			cstrwFile+=L".dll";
			CString cstrLocFile(m_wstrDll);
			cstrLocFile+=_T(".dll");
			if(FALSE==CeCpyFl2Dev(cstrLocFile.GetBuffer(), cstrwFile.GetBuffer(), TRUE))
			{
				MessageBox(NULL,_T("Can't Create file on device!"), NULL, MB_OK);
				CeRapiUninit();
				return FALSE;
			}

			if(FAILED(CeRapiInvoke(	m_wstrDll, m_wstrFun, NULL,
				NULL, &cbOut, NULL, &m_pStream, 0)))
			{
				MessageBox(NULL,_T("CeRapiInvoke faild!"), NULL, MB_OK);
				CeRapiUninit();
				return FALSE;
			}
		}
		
		if(ERROR_CALL_NOT_IMPLEMENTED==dwErr)
		{
			// invalid dll
			MessageBox(NULL,_T("Not correct dll version in deive!"), NULL, MB_OK);
			CeRapiUninit();
			return FALSE;
		}
	}
 
	DWORD dwTimeOut=*static_cast<DWORD*>(pv);
	VERIFY(SUCCEEDED(m_pStream->SetRapiStat( STREAM_TIMEOUT_READ, 3)));

	m_pExpIStrm=new CExpIStrm(reinterpret_cast<IStream*>(m_pStream));
	m_pRAPIPS=new CRAPIObjPS(m_pExpIStrm);

	m_fCnnct=TRUE;

	return TRUE;
}

void CEMemSpace::DisConnect()
{
	m_fCnnct=FALSE;
	if(NULL!=m_pRAPIPS){delete m_pRAPIPS; m_pRAPIPS=NULL;};
	if(NULL!=m_pExpIStrm){delete m_pExpIStrm; m_pExpIStrm=NULL;};
	m_pStream=NULL;
	CeRapiUninit();
}

BOOL CEMemSpace::Read(DWORD dwRdAddr, BYTE* pbBuf, DWORD dwSize)
{
	if(TRUE==m_fCnnct)
	{
		BOOL fRet=FALSE;
		// set para
		m_RAPIObjRdMem.m_arg1.Set(dwRdAddr);
		m_RAPIObjRdMem.m_arg2.Set(pbBuf, dwSize);
		m_RAPIObjRdMem.m_arg3.Set(dwSize);
		try
		{
			//start call process
			fRet=m_pRAPIPS->Call("RdMem", &m_RAPIObjRdMem);
		}
		catch (CIStrmExp e)
		{
			TRACE(_T("CRAPIObjPS::Call Transfer error!\r\n"));
			e.what();
			m_fCnnct=FALSE;
			NotifyStatChange();
			return FALSE;
		}

		if(FALSE!=fRet)
		{
			// get result
			fRet=m_RAPIObjRdMem.m_ret.m_Val;
		}
		// free resouce
		m_RAPIObjRdMem.Free();
		return fRet;
	}

	return FALSE;
}

BOOL CEMemSpace::Write(DWORD dwWtAddr, BYTE* pbBuf, DWORD dwSize)
{
	BOOL fRet=FALSE;
	if(TRUE==m_fCnnct)
	{
		// set para
		m_RAPIObjWtMem.m_arg1.Set(dwWtAddr);
		m_RAPIObjWtMem.m_arg2.Set(pbBuf, dwSize);
		m_RAPIObjWtMem.m_arg3.Set(dwSize);

		try
		{
			//start call process
			fRet=m_pRAPIPS->Call("WtMem", &m_RAPIObjWtMem);
		}
		catch (CIStrmExp e)
		{
			TRACE(_T("CRAPIObjPS::Call Transfer error!\r\n"));
			e.what();
			m_fCnnct=FALSE;
			NotifyStatChange();
			return FALSE;
		}

		if(FALSE!=fRet)
		{
			// get result
			fRet=m_RAPIObjWtMem.m_ret.m_Val;
		}
		// free resouce
		m_RAPIObjWtMem.Free();
		return fRet;
	}

	return FALSE;
}